BitTorrent: MagnetLink and BitTorrent Download
This module provides BT(BitTorrent) download resource function and supports adding download task through BT seed or magnet URL.
This module is provided in EdgerOS 2.2.10 and later.
User can use the following code to import the bittorrent
module.
const { Session } = require('bittorrent');
Support
The following shows bittorrent
module APIs available for each permissions.
User Mode | Privilege Mode | |
---|---|---|
Session | ● | ● |
session.addTorrent | ● | ● |
session.rmTorrent | ● | ● |
session.getTorrent | ● | ● |
session.isPaused | ● | ● |
session.pause | ● | ● |
session.resume | ● | ● |
session.start | ● | ● |
session.stop | ● | ● |
torrent.id | ● | ● |
torrent.metadata | ● | ● |
torrent.isFinish | ● | ● |
torrent.isPaused | ● | ● |
torrent.start | ● | ● |
torrent.stop | ● | ● |
torrent.pause | ● | ● |
torrent.resume | ● | ● |
torrent.clear | ● | ● |
torrent.setPriorities | ● | ● |
torrent.getFiles | ● | ● |
torrent.save | ● | ● |
Session Class
new Session([params])
params
{Object} Session params.- Returns: {Object} Session object.
Create a session object.
params
includes:
persistence
{Boolean} Save session state or not, default: false.sessionFile
{String} Save session state file. Whenpersistence
is valid, this path will be used. default: '.session'.updatePeriod
{Integer} (ms) session status update cycle. All requests in the session are responded to through status updates.default: 5000ms.maxUploads
{Integer} the maximum number of peers that's unchoked at the same time on this torrent. default: -1, infinite.maxConnections
{Integer} the maximum number of connection this torrent will open. If all connections are used up, incoming connections may be refused or poor connections may be closed. This must be at least 2. default: -1, unlimited.uploadLimit
{Integer} (byte/s) limit the upload bandwidth used by this particular torrent to the limit you set. It is given as the number of bytes per second the torrent is allowed to upload. default: -1, unlimited.downloadLimit
{Integer} (byte/s) limit the download bandwidth used by this particular torrent to the limit you set. It is given as the number of bytes per second the torrent is allowed to download. default: -1, unlimited.debug
{Boolean} default: false Output debugging information or not.
Example
const session = new Session({ persistence: true, debug: true });
Session Object
session.addTorrent(params)
params
{Object} Add torrent params.- Returns: promise object of
torrent
: {Torrent} result.
Add torrent to session.
params
includes:
torrentFile
{String} seed file path of torrent.magnetUrl
{String} magnet url of torrent.EithertorrentFile
ormagnetUrl
must be provided,torrentFile
prioritymagnetUrl
, if both are valid.torrentFile
takes priority overmagnetUrl
if both are valid.persistence
{Boolean} default: true. Ifpersistence
is enabled,resumeFile
param is effective. When adding a torrent to a session, if aresumeFile
file exists, the state of the torrent will be loaded. Otherwise, aresumeFiles
file will be created. When downloading a torrent, the state of the torrent will be saved.resumeFile
{String} default: './<torrent_hash>.resume'. This param is valid whenpersistence
is enable. The state of the torrent will be loaded and saved to this file.savePath
{String} default: '.'. Torrent data save to this file.maxUploads
{Integer} the maximum number of peers that's unchoked at the same time on this torrent. default to session parammaxUploads
.maxConnections
{Integer} the maximum number of connection this torrent will open. If all connections are used up, incoming connections may be refused or poor connections may be closed. This must be at least 2. default to session parammaxConnections
.uploadLimit
{Integer} (byte/s) limit the upload bandwidth used by this particular torrent to the limit you set. It is given as the number of bytes per second the torrent is allowed to upload. default to session paramuploadLimit
.downloadLimit
{Integer} (byte/s) limit the download bandwidth used by this particular torrent to the limit you set. It is given as the number of bytes per second the torrent is allowed to download. default to session paramdownloadLimit
.
Example
session.addTorrent({
persistence: true,
torrentFile: './ubuntu-24.10-desktop-amd64.iso.torrent'
})
.then(torrent => {
console.info('add torrent success:', torrent.id);
});
session.rmTorrent(idOrTorrent[, option])
idOrTorrent
{String | Torrent} Torrent id or torrent object.option
{Object} Remove torrent option.del
{Boolean} default: false. Delete torrent data when remove torrent ifdel
set totrue
.
- Returns: promise object of torrent
id
: {String} result.
Remove torrent to session.
Example
session.rmTorren(torrent, {
del: true
})
.then((id) => {
console.info('remove torrent success:', id);
});
session.getTorrent(id)
id
{String} Torrent id.- Returns: {Torrent | undefined} Get torrent object if exist.
Get torrent object.
Example
var torrent = session.getTorrent('e2467cbf021192c241367b892230dc1e05c0580e');
session.isPause
- {Boolean}
Session is pause or not.
session.pause()
- Returns: {Boolean} success or not.
Pause session. Pausing the session has the same effect as pausing every torrent in it. Resuming will restore the torrents to their previous paused state. i.e. the session pause state is separate from the torrent pause state. A torrent is inactive if it is paused or if the session is paused.
Example
session.pause();
session.resume()
- Returns: {Boolean} success or not.
Resume session.
Example
session.resume();
session.start()
State session. Periodically update the torrents status, with the period specified by the updatePeriod
param.
Example
session.start();
session.stop()
- Returns: promise object.
Stop all torrents, stop update torrents status.
Example
session.stop()
.then(() => {
console.info('session stop.');
});
Session Object Events
Session
class inherit from EventEmitter
, The following events are thrown in some specific situations.
error
Session error event.
Example
session.on('error', (err) => {
console.error(err.message);
session.stop();
});
Torrent Object
torrent.id
- {String}
Torrent id which is torrent's hash.
torrent.metadata
- {Object}
name
{String} Torrent resource name.size
{Integer} Torrent resource size(byte).files
{Array} Torrent file object list.
Torrent metadata info. metadata
value is null
when torrent object create until metadata
event is emited.
metadata
file object include:
name
{String} File name.size
{Integer} File size(byte).priority
{Integer} File download priority, detail to see:torrent.setPriorities
.
If a torrent object is created from a seed file, metadata information will be parsed from the seed file; If the torrent object is created from a magnet URL, the torrent will retrieve metadata information from the downloaded metadata data.
torrent.isFinish()
Torrent is finished or not.
torrent.isPause()
Torrent is pause or resume。
torrent.start()
- Returns: {Boolean}
false
- torrent state invalid.
Start torrent download, Torrent will turn to resume. Before starting, you should check the file download priority and set an appropriate priority.
Example
torrent.start();
torrent.stop([force])
force
{Boolean} default: false. Ifforce
is false, torrent will save state before stop.- Returns: promise object.
Stop torrent. It will call the session.rmTorrent
interface to remove the torrent If the torrent has already started, it will trigger the stop
event. Torrent stop will ultimately trigger the destroy
event.
Example
torrent.stop()
.then(() => {
console.info('torrent stop.');
});
torrent.pause()
- Returns: {Boolean}
false
- torrent state invalid.
Pause torrent. Torrent will notify status changes through the pause
event.
Example
torrent.pause();
torrent.resume()
- Returns: {Boolean}
false
- torrent state invalid.
Resume torrent. Torrent will notify status changes through the resume
event.
Example
torrent.resume();
torrent.clear()
- Returns: {Boolean}
false
- torrent state invalid.
If the torrent is in an error state, this will clear the error and start the torrent again.
torrent.setPriorities(priorities)
priorities
{Array} priorities object array, object:index
{Integer} the file index, range [0 - max_file_index]. File index order the save astorrent.metadata.files
.prio
{Integer} the file download priority.The enumeration value is defined bybittorrent.PRIO
.
- Returns: {Boolean} Set priorities success or not. This api will throw error if argument error.
bittorrent.PRIO
defined:
DONT
: Don't download the file. Partial pieces may still be downloaded when setting file priorities.DEFAULT
: The default priority for files.LOW
: The lowest priority for files.TOP
: The highest priority for files.
Set torrent file priorities. The priority is set by default(DEFAULT
) when creating a torrent. Setting the file priority to DONT
can abort the download of the file. When the file priority changes, the torrent object will emit the priority
event.
Example
const { PRIO } = require('bittorrent');
torrent.setPriorities({ 0, PRIO.DONT });
torrent.getFiles()
- Returns: promise object of
files
{Array}, array item {Object}:name
{String} File name.size
{Integer} File total size(byte).priority
{Integer} File download priority, detail to see:torrent.setPriorities
.download
{Integer} Downloaded size(byte).progress
{Float} File progress[0-1]rate
{Integer} payload download real time rate(byte/s). This rate is calculated based on the simulated value obtained from each query download data statistics.
Get torrent files attribute.
Example
torrent.getFiles()
.then((files) => {
console.info('torrent files:', JSON.stringify(files));
});
save([force])
force
{Boolean} Force save or not. default: false- Returns: promise object.
Save torrent state if the persistence
param is enabled when adding a torrent. Torrent automatically saves state periodically, and users generally do not need to call save()
.
This method is reentrant. When the force
is true, the torrent will submit a new save request whether the previous save request has been completed or not. When the force is false, do not resubmit the save request if there are previous unfinished save requests.
Example
torrent.save(true)
.then(() => {
console.info('torrent state save success.');
});
Torrent Object Events
Torrent
class inherit from EventEmitter
, The following events are thrown in some specific situations.
metadata
metadata
{Object}name
{String} Torrent resource name.size
{Integer} Torrent resource size(byte).files
{Array} Torrent file object list.
metadata
file object include:
name
{String} File name.size
{Integer} File size(byte).priority
{Integer} File download priority, detail to see:torrent.setPriorities
.
This event occurred during torrent parsed or downloaded metadata data. The torrent ready to download payload after metadata
event, call torrent.start() to start downloading data.
Example
torrent.on('metadata', (metadata) => {
console.info('torrent metadata: ', JSON.stringify(metadata));
});
puase
Torrent paused.
resume
Torrent resumed.
finish
Torrent data download completed.
Example
torrent.on('finish', () => {
console.info('torrent finish:', torrent.id);
});
stop
Torrent stopped. This event will only be triggered when the torrent is stopped after it has successfully started. Torrent prohibits all activities.
torrent.stop
or session.rmTorrent
will trigger this event.
destroy
Torrent destroy. When the torrent is stopped or removed from the session, this event will be triggered when the torrent is successfully destroyed. This event is the last event of torrent, after which the task activity will be invalid.
priority
priorities
{Array} item index the same as torrent files index. item value defined byTorrent.PRIO
, detail to see:torrent.setPriorities
.
This event occurred when torrent files priorities change. metadata.files` priorities are updated synchronously.
Example
torrent.on('priority', (priorities) => {
console.info('torrent change priorities: ', JSON.stringify(priorities));
});
update
status
{Object}state
{String} the main state the torrent is in.total_download
{Integer} the number of bytes downloaded to all peers, accumulated, this session only. The session is considered to restart when a torrent is paused and restarted again. When a torrent is paused, these counters are reset to 0. If you want complete, persistent, stats, see all_time_download.total_payload_download
{Integer} counts the amount of bytes received this session, but only the actual payload data (i.e the interesting data), these counters ignore any protocol overhead. The session is considered to restart when a torrent is paused and restarted again. When a torrent is paused, these counters are reset to 0.total_done
{Integer} the total number of bytes of the file(s) that we have. All this does not necessarily has to be downloaded during this session (that's total_payload_download).total
{Integer} the total number of bytes to download for this torrent. This may be less than the size of the torrent in case there are pad files. This number only counts bytes that will actually be requested from peers.total_wanted_done
{Integer} the number of bytes we have downloaded, only counting the pieces that we actually want to download. i.e. excluding any pieces that we have but have priority 0 (i.e. not wanted). Once a torrent becomes seed, any piece- and file priorities are forgotten and all bytes are considered "wanted".total_wanted
{Integer} The total number of bytes we want to download. This may be smaller than the total torrent size in case any pieces are prioritized to 0, i.e. not wanted. Once a torrent becomes seed, any piece- and file priorities are forgotten and all bytes are considered "wanted".all_time_download
{Integer} are accumulated download payload byte counters. They are saved in and restored from resume data to keep totals across sessions.progress
{Integer} a value in the range [0, 1], that represents the progress of the torrent's current task. It may be checking files or downloading.progress_ppm
{Integer} progress parts per million (progress * 1000000) when disabling floating point operations, this is the only option to query progress. reflects the same value as progress, but instead in a range [0, 1000000] (ppm = parts per million). When floating point operations are disabled, this is the only alternative to the floating point value in progress.download_rate
{Integer} the total rates for all peers for this torrent. The rates are given as the number of bytes per second.download_payload_rate
{Integer} the total transfer rate of payload only, not counting protocol chatter. This might be slightly smaller than the other rates, but if projected over a long time (e.g. when calculating ETA:s) the difference may be noticeable.num_seeds
{Integer} the number of peers that are seeding that this client is currently connected to.num_peers
{Integer} the number of peers this torrent currently is connected to.is_seeding
{Boolean} true if all pieces have been downloaded.is_finished
{Boolean} true if all pieces that have a priority > 0 are downloaded. There is only a distinction between finished and seeding if some pieces or files have been set to priority 0, i.e. are not downloaded.has_metadata
{Boolean} true if this torrent has metadata (either it was started from a .torrent file or the metadata has been downloaded).has_incoming
{Boolean} true if there has ever been an incoming connection attempt to this torrent.need_save_resume
{Boolean} true if this torrent has unsaved changes to its download state and statistics since the last resume data was saved.announcing_to_trackers
,announcing_to_lsd
,announcing_to_dht
{Boolean} these are set to true if this torrent is allowed to announce to the respective peer source. Whether they are true or false is determined by the queue logic/auto manager. Torrents that are not auto managed will always be allowed to announce to all peer sources.hash
{String} torrent hash string.
Torrent downloading status. This event is triggered by session update states, see (updatePeriod
)[## new Session([params])].
Example
torrent.on('update', (status) => {
console.info('torrent on status:', JSON.stringify(status));
});
/* result em:
{
"state": "downloading",
"total_download": 0,
"total_payload_download": 0,
"total_done": 117161984,
"total": 5665497088,
"total_wanted_done": 117161984,
"total_wanted": 5665497088,
"all_time_download": 117161984,
"progress": 0.02067900076508522,
"progress_ppm": 20679,
"download_rate": 0,
"download_payload_rate": 0,
"num_seeds": 0,
"num_peers": 0,
"is_seeding": false,
"is_finished": false,
"has_metadata": true,
"has_incoming": false,
"need_save_resume": false,
"announcing_to_trackers": true,
"announcing_to_lsd": true,
"announcing_to_dht": true,
"hash": "3f9aac158c7de8dfcab171ea58a17aabdf7fbc93"
} */
error
Torrent error event.
Example
torrent.on('error', (err) => {
console.error('torrent error:', err.message);
session.rmTorrent(torrent);
});
Example
const { Session, PRIO } = require('bittorrent');
const session = new Session({ persistence: true });
session.addTorrent({
persistence: true,
magnetUrl: 'magnet:?xt=urn:btih:ZOCMZQIPFFW7OLLMIC5HUB6BPCSDEOQU'
})
.then(torrent => {
console.info('add torrent success:', torrent.id);
/*
* get metadata info, choose download files and start download.
*/
torrent.on('metadata', (metadata) => {
console.info('torrent metadata: ', JSON.stringify(metadata));
/*
* download all files: set all files priority to default.
*/
let prios = [];
metadata.files.forEach((file, index) => {
if (file.priority === PRIO.DONT) {
prios.push({ index, prio: PRIO.DEFAULT });
}
});
if (prios.length > 0) {
torrent.setPriorities(prios);
}
/*
* start torrent(or stop on this point while recv metadata)
*/
torrent.start();
/*
* get files progress period(can also reset files priority on downloading)
*/
setTimeout(_ => {
torrent.getFiles()
.then(info => {
console.info('torrent files: ', JSON.stringify(info));
})
.catch(err => console.warn(err.message));
}, 10000);
});
torrent.on('finish', () => {
console.info('torrent finish:', torrent.id);
});
torrent.on('destroy', () => {
console.info('torrent destroy:', torrent.id);
});
torrent.on('error', (err) => {
console.error('torrent error:', err.message);
session.rmTorrent(torrent);
});
torrent.on('update', (status) => {
console.info('torrent on status:', JSON.stringify(status));
});
})
.catch(err => {
console.error('add torrent fail:', err.message);
});
session.start();
require('iosched').forever();